using TrackSystem.Entities.Extensions;
using TrackSystem.IO.Alarm;
using TrackSystem.IO.Data;
using TrackSystem.IO.Models;

namespace TrackSystem.IO.Protocol
{
    /// <summary>
    /// 摄像机镜头通信协议（串口）
    /// 0-zoom wide 
    /// 1-zoom Tele 
    /// 2-zoom stop
    /// 3-focus far 
    /// 4-focus near 
    /// 5-focus stop 
    /// 6-auto focus
    /// 7-iris auto 
    /// 8-iris manual 
    /// 9-iris up 
    /// 10-iris down
    /// </summary>
    public class CameraProtocl : ProtocolBase
    {
        private int startTicks;
        private int repeatTimes;    //写入操作重复次数

        private readonly int roLength;
        private readonly int rwLength;

        private byte[] r_cmd1, r_cmd2;       //校准
        private bool bSendR, bSendW;     // 发送标志

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="name"></param>
        public CameraProtocl(string name, int roLength, int rwLength)
            : base()
        {
            Name = name;
            this.roLength = roLength;
            this.rwLength = rwLength;
            Tx_w = new byte[6] { 0x81, 0x01, 0x04, 0x07, 0x30, 0xFF };
            r_cmd1 = new byte[11] { 0x07, 0x07, 0x07, 0x08, 0x08, 0x08, 0x18, 0x3E, 0x3E, 0x0E, 0x0E};
            r_cmd2 = new byte[11] { 0x30, 0x20, 0x00, 0x02, 0x03, 0x00, 0x01, 0x03, 0x02, 0x02, 0x03};

            bSendR = false;
            bSendW = false;
            NeedInit = true;
        }

        /// <summary>
        /// 生成读取寄存器的通讯帧
        /// </summary>
        /// <returns></returns>
        public override byte[] GenerateReadFrame(out int NeedRecvLen)
        {
            startTicks = Environment.TickCount;
            if (NeedInit) {
                for (int i = 0; i < rwLength; i++) {
                    RegFactory.Instance.SetVal(RegNameList[i], 0);
                }
                NeedInit = false;
            }
            NeedRecvLen = 0;
            return null;
        }


        /// <summary>
        /// 根据收到的内容进行处理
        /// </summary>
        /// <param name="buffer"></param>
        /// <returns></returns>
        public override bool ProcessReadFrame(byte[] buffer)
        {
            Rx_r = buffer;
            Lapse = Environment.TickCount - startTicks;
            return true;
        }


        /// <summary>
        /// 生成写入寄存器的通讯帧
        /// </summary>
        /// <param name="NeedRecvLen"></param>
        /// <returns></returns>
        public override byte[] GenerateWriteFrame(out int NeedRecvLen)
        {
            startTicks = Environment.TickCount;
            // 待写入的数据队列非空 
            if (writeQueue.Count() > 0)
            {
                repeatTimes = 3;    // 写入的重复次数更新为3次
            }
            // 生成写入数据帧
            if (WriteFlag && repeatTimes-- > 0)
            {
                while (writeQueue.TryDequeue(out AddressAndVal data))
                {
                    if (data.Value == 1)
                    {
                        Tx_w[3] = r_cmd1[data.Address];
                        Tx_w[4] = r_cmd2[data.Address];
                        RegFactory.Instance.SetVal(RegNameList[data.Address], 1);
                        //break;
                    }
                    else {
                        NeedRecvLen = 0;
                        return null;
                    }
                }
                
                // 上次没有收到正确的返回帧
                if (bSendW)
                {
                    Fail_W++;
                    Succ_W = 0;
                }
                bSendW = true;
                NeedRecvLen = 0;
                return Tx_w;
            }

            // 如果写入次数超过三次未成功，则将队列清空
            if (repeatTimes <= 0)
            {
                AlarmFactory.Instance.Insert("Write data error, more than three attempts",
                    AlarmCategory.COMM, Name, 0);

                // 标志位复位 重启下一个批次的读写任务
                WriteFlag = false;
            }
            NeedRecvLen = 0;
            return null;
        }

        /// <summary>
        /// 根据收到的内容进行处理
        /// </summary>
        /// <param name="buffer"></param>
        /// <returns></returns>
        public override bool ProcessWriteFrame(byte[] buffer)
        {
            Lapse = Environment.TickCount - startTicks;

            int nLen = buffer.Length;
            Rx_w = buffer;
            Succ_W++;
            bSendW = false;
            Fail_W = 0;  // 通信成功，则将失败次数清零
            WriteFlag = false;
            repeatTimes = 0;
            return true;
        }
        public override void PushRegValue(int Index, double Value)
        {
            Index -= roLength;  //寄存器存储顺序从0开始，先是只读存储器，后面是读写存储器

            if (Index >= 0 && (Index < rwLength))
            {
                writeQueue.Enqueue(new AddressAndVal(Index, Value));
                WriteFlag = true;
            }
        }
    }
}

